package com.coin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coin.domain.*;
import com.coin.dto.*;
import com.coin.feign.*;
import com.coin.mapper.*;
import com.coin.service.*;
import com.coin.vo.*;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 李力
 * @description 针对表【cash_recharge(充值表)】的数据库操作Service实现
 * @createDate 2025-06-12 10:12:53
 */
@Service
public class CashRechargeServiceImpl extends ServiceImpl<CashRechargeMapper, CashRecharge>
        implements CashRechargeService {

    @Autowired
    private SysMemberFeignClient sysUserFeignClient;

    @Autowired
    private ConfigService configService;

    @Autowired
    private AdminBankServiceFeign adminBankServiceFeign;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private CoinService coinService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private CashRechargeAuditRecordMapper cashRechargeAuditRecordMapper;

    @Autowired
    private AccountService accountService;

    /**
     * @Description: 条件分页查询
     * @Author: 李 力
     * @Date: 2025/6/13
     * @Param:
     * @return: R
     */
    @Override
    public Page<CashRecharge> findByPage(Page<CashRecharge> page, Long coinId, Long userId, String userName, String mobile, Byte status, String numMin, String numMax, String startTime, String endTime) {
        LambdaQueryWrapper<CashRecharge> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(coinId != null, CashRecharge::getCoinId, coinId)
                .eq(userId != null, CashRecharge::getUserId, userId)
                .eq(status != null, CashRecharge::getStatus, status)
                .ge(StrUtil.isNotEmpty(numMin), CashRecharge::getNum, new BigDecimal(numMin))
                .le(StrUtil.isNotEmpty(numMax), CashRecharge::getNum, new BigDecimal(numMax))
                .between(StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime), CashRecharge::getCreated, startTime, endTime);
        Map<Long, UserDto> userDtoMap = new HashMap<>();
        if (userId != null || StrUtil.isNotEmpty(userName) || StrUtil.isNotEmpty(mobile)) {
            userDtoMap = sysUserFeignClient.getBasicUsers2(userId == null ? null : Collections.singletonList(userId), userName, mobile);
            if (CollectionUtil.isEmpty(userDtoMap)) {
                return page;
            }
        }
        Page<CashRecharge> rechargePage = page(page, queryWrapper);
        List<CashRecharge> records = rechargePage.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            Map<Long, UserDto> finalUserDtoMap = userDtoMap;
            records.forEach(cashRecharge -> {
                cashRecharge.setUsername(finalUserDtoMap.get(cashRecharge.getUserId()).getUsername());
                cashRecharge.setRealName(finalUserDtoMap.get(cashRecharge.getUserId()).getRealName());
            });
        }
        return rechargePage.setRecords(records);
    }

    /**
     * @Description: GCN的充值操作
     * @Author: 李 力
     * @Date: 2025/6/13
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CashTradeVo buy(Long userId, CashParam cashParam) {
        if (userId == null || cashParam == null) {
            throw new RuntimeException("参数为空");
        }
        checkCashParam(cashParam);
        //查询公司银行卡
        List<AdminBankDto> allAdminBanks = adminBankServiceFeign.getAllAdminBanks();
        //随机挑选一张银行卡
        AdminBankDto adminBankDto = loadbalancer(allAdminBanks);
        String orderNo = String.valueOf(snowflake.nextId());
        String remark = RandomUtil.randomNumbers(6);
        Coin coin = coinService.getById(cashParam.getCoinId());
        if (coin == null) {
            throw new IllegalArgumentException("币种不存在");
        }
        Config buyGCNRate = configService.getConfigByCode("CNY2USDT");
        BigDecimal realMum = cashParam.getMum().multiply(new BigDecimal(buyGCNRate.getValue())).setScale(2, RoundingMode.HALF_UP);
        //构建新增对象
        CashRecharge cashRecharge = new CashRecharge();
        cashRecharge.setUserId(userId);
        cashRecharge.setName(adminBankDto.getName());
        cashRecharge.setBankName(adminBankDto.getBankName());
        cashRecharge.setBankCard(adminBankDto.getBankCard());
        cashRecharge.setTradeno(orderNo);
        cashRecharge.setCoinId(cashParam.getCoinId());
        cashRecharge.setCoinName(coin.getName());
        cashRecharge.setNum(cashParam.getNum());
        cashRecharge.setMum(realMum); // 实际的交易金额
        cashRecharge.setRemark(remark);
        cashRecharge.setFee(BigDecimal.ZERO);
        cashRecharge.setType("linepay"); // 在线支付
        cashRecharge.setStatus((byte) 0); // 待审核
        cashRecharge.setStep((byte) 1);// 第一步
        boolean isOk = save(cashRecharge);
        if (isOk) {
            CashTradeVo cashTradeVo = new CashTradeVo();
            cashTradeVo.setAmount(realMum);
            cashTradeVo.setStatus((byte) 0);
            cashTradeVo.setName(adminBankDto.getName());
            cashTradeVo.setBankName(adminBankDto.getBankName());
            cashTradeVo.setBankCard(adminBankDto.getBankCard());
            cashTradeVo.setRemark(remark);
            return cashTradeVo;
        }
        return null;
    }

    private AdminBankDto loadbalancer(List<AdminBankDto> allAdminBanks) {
        if (CollectionUtil.isEmpty(allAdminBanks)) {
            throw new RuntimeException("没有发现可用的银行卡");
        }
        int size = allAdminBanks.size();
        if (size == 1) {
            return allAdminBanks.get(0);
        }
        Random random = new Random();
        return allAdminBanks.get(random.nextInt(size));
    }

    private void checkCashParam(CashParam cashParam) {
        BigDecimal num = cashParam.getNum();
        Config config = configService.getConfigByCode("WITH_DROW");
        String value = config.getValue();
        BigDecimal bigDecimal = new BigDecimal(value);
        if (num.compareTo(bigDecimal) < 0) {
            throw new RuntimeException("充值数量太小");
        }
    }

    /**
     * @Description: 现金充值审核
     * @Author: 李 力
     * @Date: 2025/6/16
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cashRechargeUpdateStatus(Long userId, CashRechargeAuditRecord auditRecord) {
        if (userId == null || auditRecord == null) {
            throw new RuntimeException("参数为空");
        }
        RLock lock = redissonClient.getLock("Recharge:" + auditRecord.getId().toString());
        try {
            boolean tried = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (tried) {
                CashRecharge cashRecharge = getById(auditRecord.getId());
                if (cashRecharge == null) {
                    throw new RuntimeException("充值记录不存在");
                }
                Byte status = cashRecharge.getStatus();
                if (status == 1) {
                    throw new RuntimeException("审核已通过");
                }
                CashRechargeAuditRecord cashRechargeAuditRecordDb = new CashRechargeAuditRecord();
                cashRechargeAuditRecordDb.setAuditUserId(userId);
                cashRechargeAuditRecordDb.setStatus(auditRecord.getStatus());
                cashRechargeAuditRecordDb.setRemark(auditRecord.getRemark());
                int step = cashRecharge.getStep().byteValue() + 1;
                cashRechargeAuditRecordDb.setStep(Byte.valueOf((byte) step));
                int insert = cashRechargeAuditRecordMapper.insert(cashRechargeAuditRecordDb);
                if (insert == 0) {
                    throw new RuntimeException("审核记录保存失败");
                }
                cashRecharge.setStatus(auditRecord.getStatus());
                cashRecharge.setAuditRemark(auditRecord.getRemark());
                cashRecharge.setStep(Byte.valueOf(status));
                if (auditRecord.getStatus().byteValue() == 2) {
                    //拒绝
                    return updateById(cashRecharge);
                } else {
                    //通过审核：给用户的账户充值
                    Boolean isOk = accountService.transferAccountAmount(userId,
                            cashRecharge.getUserId(), cashRecharge.getCoinId(), cashRecharge.getId(), cashRecharge.getNum(), cashRecharge.getFee(),
                            auditRecord.getRemark(), "cash_recharge", (byte) 1
                    );
                    if (isOk) {
                        cashRecharge.setLastTime(new Date());
                        return updateById(cashRecharge);
                    }
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            lock.unlock();
        }
        return false;
    }

    /**
     * @Description: 查询当前用户的充值记录
     * @Author: 李 力
     * @Date: 2025/6/19
     * @Param:
     * @return: R
     */
    @Override
    public Page<CashRecharge> findUserCashRecharge(Page<CashRecharge> page, Long userId, Byte status) {
        LambdaQueryWrapper<CashRecharge> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(userId != null, CashRecharge::getUserId, userId)
                .eq(status != null, CashRecharge::getStatus, status);
        return page(page, queryWrapper);
    }
}




